package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constants.admin.AuthConstants;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.model.media.vo.WmNewsVo;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    private WemediaFeign wemediaFeign;

    @Value("${fdfs.url}")
    String fileServerUrl;

    @Override
    @GlobalTransactional
    public void autoScanByMediaNewsId(Integer id) {
        //检查ID是否正确
        if (id == null) {
            log.error("自动审核的文章id为空");
            return;
        }
        //使用Feign获取wmNews的信息
        WmNews wmNews = wemediaFeign.findById(id);
        if (wmNews == null) {
            log.error("自动审核的文章不存在 id==>{}", id);
            return;
        }
        //如果文章状态为8或4，并且发布时间如果小于等于当前时间 ===>发布文章
        long publishTime = wmNews.getPublishTime().getTime();
        if ((wmNews.getStatus() == 4 || wmNews.getStatus() == 8) && publishTime <= System.currentTimeMillis()) {
            saveAppArticle(wmNews);
            return;
        }
        //如果文章状态为1，待审核文章，执行审核步骤
        if (wmNews.getStatus() == 1) {
            //抽取出文章过包含的文本内容和图片内容
            //  返回map格式:  {key: text  value: 内容字符串},     key: images    value: 图片url集合
            Map<String, Object> textAndImageMap = handleTextAndImages(wmNews);
            //阿里云文本返垃圾审核 review
            String text = (String) textAndImageMap.get("text");
            if (StringUtils.isNotBlank(text)) {
                //如果失败  状态修改为2（审核失败）  如果结果为review 状态修改为3(等待人工审核)
                boolean textResult = handleTextScan(wmNews, text);//pass blocked review
                if (!textResult) return;
            }
            //阿里云图片审核pass blocked review
            List<String> images = (List<String>) textAndImageMap.get("images");
            if (images != null && !images.isEmpty()) {
                boolean imagesResult = handleImagesScan(wmNews, images);
                if (!imagesResult) return;
            }
            //查询敏感词库 并进行敏感词审核
            if (StringUtils.isNotBlank(text)) {
                //  如果查询内容中包含敏感词 修改状态为2 （审核失败）
                boolean sensitiveResult = handleSensitive(wmNews, text);
                if (!sensitiveResult) return;
            }
            //如果审核通过
            if (publishTime <= System.currentTimeMillis()) {
                // 判断 发布时间 小于等于当前时间 发布改文章
                saveAppArticle(wmNews);
            } else {
                //否则 将文章状态改为8  代表自动审核通过
                updateWmNews(wmNews, (short) 8, "审核通过");
            }

            return;
        }

    }

    @Override
    public ResponseResult findNews(NewsAuthDto dto) {
        //检查参数
        if(dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //远程调用自媒体服务获取文章列表
        PageResponseResult list = wemediaFeign.findList(dto);
        list.setHost(fileServerUrl);
        return list;
    }

    @Override
    public ResponseResult findOne(Integer id) {
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult updateByStatus(NewsAuthDto dto, Integer type) {
        //检查参数
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //根据id查询wmNews的数据
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        // 0驳回  1通过
        if(type == 0){
            updateWmNews(wmNews,(short)2,dto.getTitle());
        }else if (type == 1){
            updateWmNews(wmNews,(short)4,"人工审核通过");
        }
        return ResponseResult.okResult();
    }

    @Autowired
    private AdSensitiveMapper adSensitiveMapper;

    /**
     * @param wmNews
     * @param text
     * @return
     */
    private boolean handleSensitive(WmNews wmNews, String text) {
        // 查询出数据库中维护的敏感词列表
        List<String> allSensitive = adSensitiveMapper.findAllSensitive();
        // 将敏感词列表封装成DFA需要的数据模型( map)
        SensitiveWordUtil.initMap(allSensitive);
        log.info("敏感词列表加载完成 ==> {}", SensitiveWordUtil.dictionaryMap);
        // 使用DFA进行敏感词过滤，在过滤结果中查看是否有敏感词
        Map<String, Integer> sensitiveResult = SensitiveWordUtil.matchWords(text);
        if (sensitiveResult != null && sensitiveResult.size() > 0) {
            updateWmNews(wmNews, (short) 2, "文本中包含敏感词，审核失败");
            log.info("发现敏感词 ==> {}", sensitiveResult);
            return false;
        }

        return true;

    }

    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private FastDFSClient fastDFSClient;


    /**
     * 阿里云图片审核
     *
     * @param wmNews
     * @param images
     * @return
     */
    private boolean handleImagesScan(WmNews wmNews, List<String> images) {
        // 传入的图片集合为路径集合需要转化成 byte[] 集合
        List<byte[]> imageByteList = new ArrayList<>();
        for (String url : images) {
            // 干掉前缀 group1/xx/xx/xx/xx.jpg
            String imgUrl = url.replace(fileServerUrl, "").trim();
            //  获取 "/" 的下标
            int index = imgUrl.indexOf("/");
            //  截取分组名 和 文件名
            // group1
            String groupName = imgUrl.substring(0, index);
            //  xx/xx/xx/xx.jpg
            String path = imgUrl.substring(index + 1);
            try {
                imageByteList.add(fastDFSClient.download(groupName, path));
            } catch (IOException e) {
                e.printStackTrace();
                log.error("fastdfs下载图片失败==> group={} path={}", groupName, path);
            }
        }
        try {
            Map map = greenImageScan.imageScan(imageByteList);
            String suggest = (String) map.get(AuthConstants.AUTH_SUGGESTION);
            if (AuthConstants.AUTH_PASS.equals(suggest)) {
                // 审核通过
                return true;
            } else if (AuthConstants.AUTH_REVIEW.equals(suggest)) {
                updateWmNews(wmNews, (short) 3, "图片中有不确定因素，需要进行人工审核");
            } else {
                updateWmNews(wmNews, (short) 2, "图片中有违规，图片审核失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("调用阿里云图片检测服务失败==>{}", e.getMessage());
        }
        return false;
    }

    @Autowired
    private GreenTextScan greenTextScan;//文本扫描

    /**
     * 阿里云文章审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean handleTextScan(WmNews wmNews, String text) {
        try {
            Map map = greenTextScan.greeTextScan(text);
            //获取待审核的字段
            String suggest = (String) map.get(AuthConstants.AUTH_SUGGESTION);

            if (AuthConstants.AUTH_PASS.equals(suggest)) {
                //审核通过
                return true;
            } else if (AuthConstants.AUTH_REVIEW.equals(suggest)) {
                //需要人工审核修改状态
                updateWmNews(wmNews, (short) 3, "文章内容中有不确定因素,需要人工审核");

            } else {
                //修改为审核失败的状态
                updateWmNews(wmNews, (short) 2, "文章内容中友违规信息，审核失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核出现异常，当前审核新闻ID==>{} 异常原因==>{}", wmNews.getId(), e.getMessage());
        }
        return false;
    }

    /**
     * 修改自媒体新闻
     *
     * @param wmNews 新闻对象
     * @param status 状态
     * @param msg    原因
     */
    private void updateWmNews(WmNews wmNews, short status, String msg) {
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        wemediaFeign.updateWmNews(wmNews);
    }


    /**
     * 抽取文本内容 及 图片内容 放入map集合中
     * content key :text value:内容字符串 key: images value :图片url信息 集合
     *
     * @param
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //用于储存文本内容
        StringBuffer contentStr = new StringBuffer(wmNews.getTitle());
        //用于储存图片路径集合
        List<String> images = new ArrayList<>();

        List<Map> mapList = JSONArray.parseArray(wmNews.getContent(), Map.class);
        //遍历map集合
        for (Map map : mapList) {
            //拼接文本内容
            String type = (String) map.get("type");
            if ("text".equals(type)) {
                contentStr.append(map.get("value"));
            }
            //添加图片
            if ("image".equals(type)) {
                images.add((String) map.get("value"));

            }
        }
        //添加封面图片
        String coverImages = wmNews.getImages();
        if (StringUtils.isNotBlank(coverImages) && wmNews.getType() != 0) {
            //因为封面字段使用，逗号拼接的图片列表 需要split切割 得到图片数组
            images.addAll(Arrays.asList(coverImages.split(",")));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("text", contentStr.toString());
        map.put("images", images);
        return map;


    }

    /**
     * 发布
     *
     * @param wmNews
     */
    private void saveAppArticle(WmNews wmNews) {
        //保存ap_article表信息
        ApArticle apArticle = saveArticle(wmNews);
        //保存ap_article_config配置信息
        saveArticleConfig(apArticle);
        //保存ap_article_content文章内容表信息
        saveArticleContent(apArticle, wmNews);
        //将文章状态改为9
        wmNews.setArticleId(apArticle.getId());//关联app端的文章id
        updateWmNews(wmNews, (short) 9, "文章发布");
    }

    /**
     * 保存文章配置信息
     *
     * @param apArticle
     */
    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsComment(true);
        apArticleConfig.setIsForward(true);
        apArticleConfig.setIsDown(false);
        apArticleConfig.setIsDelete(false);
        articleFeign.saveArticleConfig(apArticleConfig);

    }

    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private AdChannelMapper adChannelMapper;

    /**
     * 保存到app端文章
     *
     * @param wmNews
     * @return
     */
    private ApArticle saveArticle(WmNews wmNews) {
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());
        apArticle.setLayout(wmNews.getType());//单图 多图 无图
        apArticle.setFlag((byte) 0);
        apArticle.setImages(wmNews.getImages());//封面图片
        apArticle.setLabels(wmNews.getLabels());
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(wmNews.getPublishTime());
        Integer userId = wmNews.getUserId(); //WmUser 的id apUserId
        //根据用户ID
        WmUser wmUser = wemediaFeign.findWmUserById(Long.valueOf(userId));
        //设置作者信息
        ApAuthor author = articleFeign.findAuthorByUserId(String.valueOf(wmUser.getApUserId()));
        if (author != null) {
            apArticle.setAuthorId(Long.valueOf(author.getId()));
            apArticle.setAuthorName(author.getName());
        }
        //设置频道信息
        AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
        if (adChannel != null) {
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }
        return articleFeign.saveArticle(apArticle);
    }

    /**
     * 保存文章内容
     *
     * @param apArticle
     * @param wmNews
     */
    private void saveArticleContent(ApArticle apArticle, WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        articleFeign.saveArticleContent(apArticleContent);
    }
}
